using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Abp.AutoMapper;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Application.Services.Dto;
using Abp.Linq.Extensions;
using Microsoft.AspNetCore.Mvc;
using Yozeev.BusinessLogic.Dtos;
using Yozeev.BusinessLogic.DomainService;
using Yozeev.BusinessLogic.DeviceManagement.DomainService;
using Yozeev.BusinessLogic.DeviceManagement.Dtos;
using Yozeev.Common;
using Abp.Authorization.Users;

namespace Yozeev.BusinessLogic
{
	/// <summary>
	/// Device应用层服务的接口实现方法  
	///</summary>
	[AbpAuthorize]
	public class DeviceAppService : YozeevAppServiceBase, IDeviceAppService
    {
        private readonly IRepository<Device, Guid> _entityRepository;

        private readonly IDeviceManager _entityManager;

        private readonly IDeviceCache _deviceCache;

        private readonly IQueryHelper _queryHelper;

		private readonly IRepository<VerifiableSet, Guid> _verifiableRepository;

		private readonly IRepository<GateRecord, Guid> _gateRecordRepository;

		/// <summary>
		/// 构造函数 
		///</summary>
		public DeviceAppService(
        IRepository<Device, Guid> entityRepository
        ,IDeviceManager entityManager
		, IDeviceCache deviceCache
		, IQueryHelper queryHelper
			, IRepository<VerifiableSet, Guid> verifiableRepository
			, IRepository<GateRecord, Guid> gateRecordRepository
		)
        {
            _entityRepository = entityRepository; 
             _entityManager=entityManager;
             _deviceCache = deviceCache;
             _queryHelper = queryHelper;
			_verifiableRepository = verifiableRepository;
			_gateRecordRepository = gateRecordRepository;
		}
        /// <summary>
        /// 获取Device的分页列表信息--Get方法
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
		public async Task<PagedResultDto<DeviceListDto>> GetPagedForGet(GetDevicesInputForGet input)
        {
			var expression = _queryHelper.WhereExp<Device>(input.queryData);
			if (AbpUserBase.AdminUserName != GetCurrentUser().UserName)
				expression = _queryHelper.SetWhereExp<Device>(expression, GetViewTypeEnum<Device>(), await GetBranchUser());
			// TODO:根据传入的参数添加过滤条件
			var query = from device in _entityRepository.GetAll().AsNoTracking()
						.Where(expression)
						select new
						{
							device,
							list = (from ts in _verifiableRepository.GetAll().AsNoTracking().Where(m => m.DeviceId == device.Id)
									select ts.VerifiableType).ToList(),
						};

			var list = new List<DeviceListDto>();
			query.ToList().ForEach(temp =>
			{
				var _entity = temp.device.MapTo<DeviceListDto>();
				_entity.VerifiableTypes = temp.list;
				list.Add(_entity);
			});
			// TODO:根据传入的参数添加过滤条件
			var count = list.Count();
			list = list.AsQueryable().OrderBy(input.Sorting)
					.PageBy(input)
					.ToList();

			return new PagedResultDto<DeviceListDto>(count, list);
        }

		/// <summary>
		/// 获取Device的分页列表信息--Post方法
		///</summary>
		/// <param name="input"></param>
		/// <returns></returns>
        [HttpPost]
        public async Task<PagedResultDto<DeviceListDto>> GetPaged(GetDevicesInput input)
		{
			var expression = _queryHelper.WhereExp<Device>(input.queryData);
			expression = _queryHelper.SetWhereExp<Device>(expression, GetViewTypeEnum<Device>(), await GetBranchUser());
			// TODO:根据传入的参数添加过滤条件
			var query = from device in _entityRepository.GetAll().AsNoTracking()
						.Where(expression)
						select new
						{
							device,
							list = (from ts in _verifiableRepository.GetAll().AsNoTracking().Where(m => m.DeviceId == device.Id)
									select ts.VerifiableType).ToList(),
						};
			var list = new List<DeviceListDto>();
			query.ToList().ForEach(temp =>
			{
				var _entity = temp.device.MapTo<DeviceListDto>();
				_entity.VerifiableTypes = temp.list;
				list.Add(_entity);
			});
			// TODO:根据传入的参数添加过滤条件
			var count = list.Count();
			list = list.AsQueryable().OrderBy(input.Sorting)
					.PageBy(input)
					.ToList();
			return new PagedResultDto<DeviceListDto>(count, list);
		}


		/// <summary>
		/// 通过指定id获取DeviceListDto信息
		/// </summary>
		public async Task<DeviceListDto> GetById(EntityDto<Guid> input)
		{
			var entity = await _entityRepository.GetAsync(input.Id);

		    return entity.MapTo<DeviceListDto>();
		}

		/// <summary>
		/// 获取编辑 Device
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task<GetDeviceForEditOutput> GetForEdit(NullableIdDto<Guid> input)
		{
			var output = new GetDeviceForEditOutput();
            DeviceEditDto editDto;

			if (input.Id.HasValue)
			{
				var query = from device in _entityRepository.GetAll().Where(m => m.Id == input.Id)
							select new
							{
								device,
								list = (from ts in _verifiableRepository.GetAll().AsNoTracking().Where(m => m.DeviceId == device.Id)
										select ts.VerifiableType).ToList(),
							};
				var temp = query.FirstOrDefault();
				editDto = temp.device.MapTo<DeviceEditDto>();
				editDto.VerifiableTypes = temp.list;

				//deviceEditDto = ObjectMapper.Map<List<deviceEditDto>>(entity);
			}
			else
			{
				editDto = new DeviceEditDto();
			}

			output.Device = editDto;
			return output;
		}


		/// <summary>
		/// 添加或者修改Device的公共方法
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task CreateOrUpdate(CreateOrUpdateDeviceInput input)
		{
			var temp = input;
			var verifiableTypes = input.Device.VerifiableTypes;
			if (input.Device.Id.HasValue)
			{
				await Update(input.Device);
				await _verifiableRepository.DeleteAsync(t => t.DeviceId == input.Device.Id);
			}
			else
			{
				temp.Device = await Create(input.Device);
			}
			//修改可验证类型
			foreach (var verifiableType in verifiableTypes)
			{
				var verifiableSet = new VerifiableSet()
				{
					VerifiableType = verifiableType,
					DeviceId = (Guid)temp.Device.Id,
					IsEnabled = true,
					CreationTime = DateTime.Now,
					CreatorUserId = AbpSession.UserId,
				};
				await _verifiableRepository.InsertAndGetIdAsync(verifiableSet);
			}
		}


		/// <summary>
		/// 新增Device
		/// </summary>
		protected virtual async Task<DeviceEditDto> Create(DeviceEditDto input)
		{
			//TODO:新增前的逻辑判断，是否允许新增

            // var entity = ObjectMapper.Map <Device>(input);
            var entity=input.MapTo<Device>();
			

			entity = await _entityRepository.InsertAsync(entity);
			return entity.MapTo<DeviceEditDto>();
		}

		/// <summary>
		/// 编辑Device
		/// </summary>
		protected virtual async Task Update(DeviceEditDto input)
		{
			//TODO:更新前的逻辑判断，是否允许更新

			var entity = await _entityRepository.GetAsync(input.Id.Value);
			input.MapTo(entity);

			// ObjectMapper.Map(input, entity);
		    await _entityRepository.UpdateAsync(entity);
		}



		/// <summary>
		/// 删除Device信息的方法
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task Delete(EntityDto<Guid> input)
		{
			//TODO:删除前的逻辑判断，是否允许删除
			var gateRecords = _gateRecordRepository.GetAll().Where(m => m.DeviceId == input.Id);
			if (gateRecords.Count() > 0)
				throw new Exception("该设备已经使用，不能删除！");
			//删除“可验票类型”相关信息
			await _verifiableRepository.DeleteAsync(t => t.DeviceId == input.Id);
			await _entityRepository.DeleteAsync(input.Id);
		}



		/// <summary>
		/// 批量删除Device的方法
		/// </summary>
		public async Task BatchDelete(List<Guid> input)
		{
			// TODO:批量删除前的逻辑判断，是否允许删除

			var gateRecords = _gateRecordRepository.GetAll().Where(m => input.Contains((Guid)m.DeviceId));
			if (gateRecords.Count() > 0)
				throw new Exception("该设备已经使用，不能删除！");
			//删除“航班可售票”相关信息
			await _verifiableRepository.DeleteAsync(t => input.Contains(t.DeviceId));
			await _entityRepository.DeleteAsync(s => input.Contains(s.Id));
		}

		/// <summary>
		/// 客户端每分钟发送一次心跳包
		/// </summary>
		/// <param name="gateNumber"></param>
		/// <returns></returns>
        public async Task<HeartBeatResult> HeartBeat(string gateNumber)
        {
			long currentTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
			_deviceCache.Put(gateNumber, currentTime);
            return new HeartBeatResult {status = 1};
        }

		/// <summary>
		/// 根据设备编号获取证件类型
		/// </summary>
		/// <param name="deviceCode">设备编号</param>
		/// <returns></returns>
		public async Task<List<IdentityTypeDto>> GetIdentityType(string deviceCode)
		{
			return _entityManager.GetIdentitiesAsync(deviceCode)
				.Select(v => new IdentityTypeDto 
				{
					IdentityName = v.IdentityName,
					IdentityType = v.IdentityType
				}).ToList();
		}

		/// <summary>
		/// 导出Device为excel表,等待开发。
		/// </summary>
		/// <returns></returns>
		//public async Task<FileDto> GetToExcel()
		//{
		//	var users = await UserManager.Users.ToListAsync();
		//	var userListDtos = ObjectMapper.Map<List<UserListDto>>(users);
		//	await FillRoleNames(userListDtos);
		//	return _userListExcelExporter.ExportToFile(userListDtos);
		//}

	}
}


